package com.qiyigu.itc.speech.xunfai;

import android.content.res.AssetManager;
import android.util.Log;

import com.iflytek.aiui.AIUIAgent;
import com.iflytek.aiui.AIUIConstant;
import com.iflytek.aiui.AIUIEvent;
import com.iflytek.aiui.AIUIListener;
import com.iflytek.aiui.AIUIMessage;
import com.iflytek.cloud.SpeechUtility;
import com.qiyigu.itc.speech.MyApp;
import com.qiyigu.itc.speech.SpeechService;
import com.qiyigu.itc.speech.service.BaseServiceImpl;
import com.qiyigu.itc.speech.service.listener.OnSpeechListener;
import com.qiyigu.itc.speech.util.Constant;

import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;

/**
 * 讯飞语音识别
 */
public class XunfaiSpeechServiceImpl extends BaseServiceImpl implements SpeechService {

    protected static XunfaiSpeechServiceImpl service = null;
    private AIUIAgent mAIUIAgent = null;
    private int mAIUIState = AIUIConstant.STATE_IDLE;

    protected OnSpeechListener onSpeechListener;

    protected XunfaiSpeechServiceImpl(OnSpeechListener onSpeechListener) {
        service = this;
        this.onSpeechListener = onSpeechListener;
        SpeechUtility.createUtility(MyApp.getInstance(), "appid=" + Constant
                .XUN_FAI_APPKEY);
        checkAIUIAgent();
    }

    public static synchronized XunfaiSpeechServiceImpl getInstance(OnSpeechListener
                                                                           onSpeechListener) {
        if (service == null) {
            service = new XunfaiSpeechServiceImpl(onSpeechListener);
        }
        return service;
    }


    @Override
    public void startSpeech() {
// 先发送唤醒消息，改变AIUI内部状态，只有唤醒状态才能接收语音输入
        // 默认为oneshot 模式，即一次唤醒后就进入休眠，如果语音唤醒后，需要进行文本语义，请将改段逻辑copy至startTextNlp()开头处
        if (AIUIConstant.STATE_WORKING != this.mAIUIState) {
            AIUIMessage wakeupMsg = new AIUIMessage(AIUIConstant.CMD_WAKEUP, 0, 0, "", null);
            mAIUIAgent.sendMessage(wakeupMsg);
        }

        // 打开AIUI内部录音机，开始录音
        String params = "sample_rate=16000,data_type=audio";
        AIUIMessage writeMsg = new AIUIMessage(AIUIConstant.CMD_START_RECORD, 0, 0, params, null);
        mAIUIAgent.sendMessage(writeMsg);
    }

    @Override
    public void stopSpeech() {
        // 停止录音
        String params = "sample_rate=16000,data_type=audio";
        AIUIMessage stopWriteMsg = new AIUIMessage(AIUIConstant.CMD_STOP_RECORD, 0, 0, params,
                null);

        mAIUIAgent.sendMessage(stopWriteMsg);
    }

    @Override
    public void releaseSpeech() {
        // 销毁合成对象
        if (null != this.mAIUIAgent) {
            AIUIMessage stopMsg = new AIUIMessage(AIUIConstant.CMD_STOP, 0, 0, null, null);
            mAIUIAgent.sendMessage(stopMsg);

            this.mAIUIAgent.destroy();
            this.mAIUIAgent = null;
        }
    }


    private String getAIUIParams() {
        String params = "";

        AssetManager assetManager = MyApp.getInstance().getResources().getAssets();
        try {
            InputStream ins = assetManager.open("xunfai/cfg/aiui_phone.cfg");
            byte[] buffer = new byte[ins.available()];

            ins.read(buffer);
            ins.close();

            params = new String(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return params;
    }

    private boolean checkAIUIAgent() {
        if (null == mAIUIAgent) {
            Log.i(TAG, "create aiui agent");
            mAIUIAgent = AIUIAgent.createAgent(MyApp.getInstance(), getAIUIParams(),
                    mAIUIListener);
            AIUIMessage startMsg = new AIUIMessage(AIUIConstant.CMD_START, 0, 0, null, null);
            mAIUIAgent.sendMessage(startMsg);
        }

        if (null == mAIUIAgent) {
            logger.e("创建 AIUI Agent 失败！");
        }

        return null != mAIUIAgent;
    }

    private AIUIListener mAIUIListener = new AIUIListener() {

        @Override
        public void onEvent(AIUIEvent event) {
            switch (event.eventType) {
                case AIUIConstant.EVENT_WAKEUP:
                    Log.i(TAG, "on event: " + event.eventType);
                    if (onSpeechListener != null) {
                        onSpeechListener.onWarkUp();
                    }
                    break;

                case AIUIConstant.EVENT_RESULT: {
                    try {
                        JSONObject bizParamJson = new JSONObject(event.info);
                        JSONObject data = bizParamJson.getJSONArray("data").getJSONObject(0);
                        JSONObject params = data.getJSONObject("params");
                        JSONObject content = data.getJSONArray("content").getJSONObject(0);

                        if (content.has("cnt_id")) {
                            String cnt_id = content.getString("cnt_id");
                            JSONObject cntJson = new JSONObject(new String(event.data
                                    .getByteArray(cnt_id), "utf-8"));

                            String sub = params.optString("sub");
                            if ("nlp".equals(sub)) {
                                // 解析得到语义结果
                                String resultStr = cntJson.optString("intent");
                                Log.d(TAG, resultStr);
                                if (onSpeechListener != null) {
                                    onSpeechListener.onResult(false, resultStr);
                                }
                            }
                        }
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                }
                break;

                case AIUIConstant.EVENT_ERROR: {
                    Log.d(TAG, "on event: " + event.eventType);
                    if (onSpeechListener != null) {
                        onSpeechListener.onResultError();
                    }
                }
                break;

                case AIUIConstant.EVENT_VAD:
                    break;

                case AIUIConstant.EVENT_START_RECORD:
                    break;

                case AIUIConstant.EVENT_STOP_RECORD:

                    break;

                case AIUIConstant.EVENT_STATE:
                    break;

                case AIUIConstant.EVENT_CMD_RETURN:
                    break;

                default:
                    break;
            }
        }

    };

}
